home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / datecls.exe / DATECLS4.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-07  |  11.6 KB  |  626 lines

  1. /*
  2.  *┌──────────────────────────────────────────────────────────────────────
  3.  *│ File.........: DATECLS4.CPP
  4.  *│ Date.........: Sunday 3/7/1993
  5.  *│ Author.......: Kenneth A. Argo (CIS 71241,3635)
  6.  *│ Copyright....: None! Use freely.
  7.  *│ Version......: 4.1    Compile w/MSC++ 7.0
  8.  *│ Usage........: General purpose date conversion, arithmetic,
  9.  *│         :    comparison, and formatting class
  10.  *│
  11.  *│ See DATE.H for acknowledgements and compile/link notes.
  12.  *└──────────────────────────────────────────────────────────────────────
  13.  */
  14.  
  15. #include "datecls4.h"
  16.  
  17. int Date::DisplayFormat=MDY;
  18.  
  19. unsigned char Date::DisplayOptions='\0';
  20.  
  21. const char *dayname[] = {"Sunday","Monday","Tuesday","Wednesday",
  22.        "Thursday","Friday","Saturday"} ;
  23.  
  24. const char *mname[] = {"January","February","March","April","May",
  25.        "June","July","August","September","October","November","December"};
  26.  
  27. static int GauDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  28.  
  29. ////////////////////////////////////////////////////////////
  30. // Constructors
  31. ////////////////////////////////////////////////////////////
  32.  
  33. Date::Date()
  34. {
  35.     month = day = day_of_week = 0;
  36.     year = 0;
  37.     julian = 0;
  38. }
  39.  
  40. Date::Date (const long j) : julian(j)
  41. {
  42.     julian_to_mdy ();
  43. }
  44.  
  45. Date::Date (const int m, const int d, const int y) : month((unsigned char)m), day((unsigned char)d), year(y)
  46. {
  47.     mdy_to_julian ();
  48. }
  49.  
  50. Date::Date (char *dat)
  51. {
  52.     if (!_stricmp(dat, "TODAY"))
  53.     {
  54.         struct _dosdate_t temp_date;
  55.         _dos_getdate(&temp_date);
  56.         month = temp_date.month;
  57.         day   = temp_date.day;
  58.         year  = temp_date.year;
  59.     }
  60.     else
  61.     {
  62.         month = (unsigned char)atoi(strtok(dat,"/-"));
  63.         day   = (unsigned char)atoi(strtok(NULL,"/-"));
  64.         year  = atoi(strtok(NULL," "));
  65.     }
  66.  
  67.     mdy_to_julian ();
  68. }
  69.  
  70. Date::Date (const _dosdate_t &ds)
  71. {
  72.     month = ds.month;
  73.     day   = ds.day;
  74.     year  = ds.year;
  75.     mdy_to_julian ();
  76. }
  77.  
  78. Date::Date (const Date &dt)
  79. {
  80.     month = dt.month;
  81.     day   = dt.day;
  82.     year  = dt.year;
  83.     mdy_to_julian ();
  84. }
  85.  
  86. Date::~Date()
  87. {
  88.     if (buf != (char *)&BadDate)
  89.         delete buf;
  90. }
  91.  
  92. //////////////////////////////////////////////////////////////
  93. // Conversion operations
  94. //////////////////////////////////////////////////////////////
  95.  
  96. Date::operator char *( void )
  97. {
  98.     buf = new char[13];
  99.  
  100.     if (day==0 || month==0 || year==0)
  101.         buf = (char *)&BadDate;
  102.     else
  103.         sprintf(buf,"%1d/%1d/%-4d",month,day,year);
  104.  
  105.     return buf;
  106. }
  107.  
  108. //////////////////////////////////////////////////////////////
  109. // Date Arithmetic
  110. //////////////////////////////////////////////////////////////
  111.  
  112. Date &Date::operator + (const long i)
  113. {
  114.     return Date(julian + i);
  115. }
  116.  
  117. Date &Date::operator + (const int i)
  118. {
  119.     return Date(julian + (long)i);
  120. }
  121.  
  122. Date &Date::operator - (const long i)
  123. {
  124.     return Date(julian - i);
  125. }
  126.  
  127. Date &Date::operator - (const int i)
  128. {
  129.     return Date(julian - (long)i);
  130. }
  131.  
  132. long Date::operator - (const Date &dt)
  133. {
  134.     return ( julian - dt.julian );
  135. }
  136.  
  137. Date &Date::operator += (const long i)
  138. {
  139.     julian += i;
  140.     julian_to_mdy();
  141.     return *this;
  142. }
  143.  
  144. Date &Date::operator -= (const long i)
  145. {
  146.     julian -= i;
  147.     julian_to_mdy();
  148.     return *this;
  149. }
  150.  
  151. Date &Date::operator ++()
  152. {
  153.     julian++;
  154.     julian_to_mdy();
  155.     return *this;
  156. }
  157.  
  158. Date &Date::operator ++(int)
  159. {
  160.     julian++;
  161.     julian_to_mdy();
  162.     return *this;
  163. }
  164.  
  165. Date &Date::operator --()
  166. {
  167.     julian--;
  168.     julian_to_mdy();
  169.     return *this;
  170. }
  171.  
  172. Date &Date::operator --(int)
  173. {
  174.     julian--;
  175.     julian_to_mdy();
  176.     return *this;
  177. }
  178.  
  179. //////////////////////////////////////////////////////////////
  180. // Date comparison
  181. //////////////////////////////////////////////////////////////
  182.  
  183. int operator <  (const Date &dt1, const Date &dt2)
  184. {
  185.     return ( dt1.julian < dt2.julian );
  186. }
  187.  
  188. int operator <= (const Date &dt1, const Date &dt2)
  189. {
  190.     return ( (dt1.julian == dt2.julian) || (dt1.julian < dt2.julian) );
  191. }
  192.  
  193. int operator >  (const Date &dt1, const Date &dt2)
  194. {
  195.     return ( dt1.julian > dt2.julian );
  196. }
  197.  
  198. int operator >= (const Date &dt1, const Date &dt2)
  199. {
  200.     return ( (dt1.julian == dt2.julian) || (dt1.julian > dt2.julian) );
  201. }
  202.  
  203. int operator == (const Date &dt1, const Date &dt2)
  204. {
  205.     return ( dt1.julian == dt2.julian );
  206. }
  207.  
  208. int operator != (const Date &dt1, const Date &dt2)
  209. {
  210.     return ( dt1.julian != dt2.julian );
  211. }
  212.  
  213. ////////////////////////////////////////////////////////////////
  214. // Ostream operations
  215. ////////////////////////////////////////////////////////////////
  216.  
  217. ostream &operator << (ostream &os, const Date &dt)
  218. {
  219.     return os << dt.formatDate();
  220. }
  221.  
  222. ostream &operator << (ostream &os, const _dosdate_t &dt)
  223. {
  224.     return os << (int)dt.month << "/" << (int)dt.day << "/" << dt.year;
  225. }
  226.  
  227. //////////////////////////////////////////////////////////////
  228. // Conversion routines
  229. //////////////////////////////////////////////////////////////
  230.  
  231. void Date::julian_to_wday (void)
  232. {
  233.     day_of_week = (unsigned char) ((julian + 2) % 7 + 1);
  234. }
  235.  
  236. void Date::julian_to_mdy ()
  237. {
  238.     long a,b,c,d,e,z,alpha;
  239.     z = julian+1;
  240.  
  241.     // dealing with Gregorian calendar reform
  242.  
  243.     if (z < 2299161L)
  244.         a = z;
  245.     else
  246.     {
  247.         alpha = (long) ((z-1867216.25) / 36524.25);
  248.         a = z + 1 + alpha - alpha/4;
  249.     }
  250.  
  251.     b = ( a > 1721423 ? a + 1524 : a + 1158 );
  252.     c = (long) ((b - 122.1) / 365.25);
  253.     d = (long) (365.25 * c);
  254.     e = (long) ((b - d) / 30.6001);
  255.  
  256.     day = (unsigned char)(b - d - (long)(30.6001 * e));
  257.     month = (unsigned char)((e < 13.5) ? e - 1 : e - 13);
  258.     year = (int)((month > 2.5 ) ? (c - 4716) : c - 4715);
  259.     julian_to_wday ();
  260. }
  261.  
  262. void Date::mdy_to_julian (void)
  263. {
  264.     int a,b=0;
  265.     int work_month=month, work_day=day, work_year=year;
  266.  
  267.     // correct for negative year
  268.  
  269.     if (work_year < 0)
  270.         work_year++;
  271.  
  272.     if (work_month <= 2)
  273.     {
  274.         work_year--;
  275.         work_month +=12;
  276.     }
  277.  
  278.     // deal with Gregorian calendar
  279.  
  280.     if (work_year*10000. + work_month*100. + work_day >= 15821015.)
  281.     {
  282.         a = (int)(work_year/100.);
  283.         b = 2 - a + a/4;
  284.     }
  285.  
  286.     julian = (long) (365.25*work_year) +
  287.              (long) (30.6001 * (work_month+1))  +  work_day + 1720994L + b;
  288.     julian_to_wday ();
  289. }
  290.  
  291. ////////////////////////////////////////////////////////////////
  292. // Format routine
  293. ////////////////////////////////////////////////////////////////
  294.  
  295. char *Date::formatDate (const int type) const
  296. {
  297.     static char buf[40];
  298.  
  299.     _strnset( buf, '\0', sizeof(buf) );
  300.  
  301.     switch ( type )
  302.     {
  303.         case DAY:
  304.  
  305.             if ( (day_of_week < 1) || (day_of_week > 7) )
  306.                 strcpy(buf,"invalid day");
  307.             else
  308.                 strncpy( buf, dayname[day_of_week-1],
  309.                     (DisplayOptions & DATE_ABBR) ? ABBR_LENGTH : 9);
  310.  
  311.             return buf;
  312.             break;
  313.  
  314.         case MONTH:
  315.  
  316.             if ( (month < 1) || (month > 12) )
  317.                 strcpy(buf,"invalid month");
  318.             else
  319.                 strncpy( buf, mname[month-1],
  320.                     (DisplayOptions & DATE_ABBR) ? ABBR_LENGTH : 9);
  321.  
  322.             return buf;
  323.             break;
  324.  
  325.         case FULL:
  326.  
  327.             if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
  328.                  (day_of_week > 7) )
  329.             {
  330.                 strcpy(buf,"invalid date");
  331.                 return buf;
  332.             }
  333.  
  334.             strncpy( buf, dayname[day_of_week-1],
  335.                 (DisplayOptions & DATE_ABBR) ? ABBR_LENGTH : 9);
  336.             strcat( buf, ", ");
  337.             strncat( buf, mname[month-1],
  338.                 (DisplayOptions & DATE_ABBR) ? ABBR_LENGTH : 9);
  339.             strcat( buf, " ");
  340.             sprintf( buf+strlen(buf), "%d, %d", day, abs(year) );
  341.  
  342.             if (year < 0)
  343.                 strcat(buf," B.C.E.");
  344.  
  345.             return buf;
  346.             break;
  347.  
  348.         case EUROPEAN:
  349.  
  350.             if ( (month < 1) || (month > 12) || (day_of_week < 0) ||
  351.                  (day_of_week > 7) )
  352.             {
  353.                 strcpy(buf,"invalid date");
  354.                 return buf;
  355.             }
  356.  
  357.             sprintf(buf,"%d ",    day);
  358.             strncat(buf, mname[month-1],
  359.                 (DisplayOptions & DATE_ABBR) ? ABBR_LENGTH : 9);
  360.             sprintf( buf+strlen(buf), " %d", abs(year) );
  361.  
  362.             if (year < 0)
  363.                 strcat(buf," B.C.E.");
  364.  
  365.             return buf;
  366.             break;
  367.  
  368.         case MDY:
  369.  
  370.         default:
  371.             if (day==0 || month==0 || year==0)
  372.                 strcpy(buf,"invalid date");
  373.             else
  374.                 sprintf( buf+strlen(buf), "%1d/%1d/%02d", month, day,
  375.                     (DisplayOptions & NO_CENTURY) && (abs(year) > 1899)
  376.                     ? (abs(year) - (abs(year) / 100 * 100))
  377.                     : (abs(year))  );
  378.  
  379.             return buf;
  380.             break;
  381.     }
  382. }
  383.  
  384. void Date::setFormat( const int format )
  385. {
  386.     DisplayFormat = format;
  387. }
  388.  
  389. int Date::setOption( const int option, const int action )
  390. {
  391.     switch ( option )
  392.     {
  393.         case NO_CENTURY:
  394.  
  395.             if ( action )
  396.                 DisplayOptions |= NO_CENTURY;
  397.             else
  398.             {
  399.                 DisplayOptions &= (~NO_CENTURY);
  400.             }
  401.  
  402.             return 1;
  403.             break;
  404.  
  405.         case DATE_ABBR:
  406.  
  407.             if ( action )
  408.                 DisplayOptions |= DATE_ABBR;
  409.             else
  410.             {
  411.                 DisplayOptions &= (~DATE_ABBR);
  412.             }
  413.  
  414.             return 1;
  415.             break;
  416.  
  417.         default:
  418.  
  419.             return 0;
  420.             break;
  421.  
  422.     }
  423. }
  424.  
  425. ///////////////////////////////////////////////////////////////
  426. //  Miscellaneous Routines
  427. ///////////////////////////////////////////////////////////////
  428.  
  429. long Date::julDate( void ) const
  430. {
  431.     return julian;
  432. }
  433.  
  434. int Date::DOY( void ) const
  435. {
  436.     Date temp( 1, 1, year );
  437.  
  438.     return (int) (julian - temp.julian + 1);
  439. }
  440.  
  441.  
  442. int Date::isLeapYear( void ) const
  443. {
  444.     return  ( (year >= 1582) ?
  445.           (year % 4 == 0  &&  year % 100 != 0  ||  year % 400 == 0 ):
  446.           (year % 4 == 0) );
  447. }
  448.  
  449. _dosdate_t Date::eom( void ) const
  450. {
  451.     static _dosdate_t eom_temp;
  452.     Date tempdate( (month % 12) + 1, 1, year);
  453.  
  454.     if (month == 12)
  455.         tempdate.year++;
  456.  
  457.     tempdate--;
  458.  
  459.     eom_temp.year  = tempdate.year;
  460.     eom_temp.month = tempdate.month;
  461.     eom_temp.day   = tempdate.day;
  462.  
  463.     return eom_temp;
  464. }
  465.  
  466. _dosdate_t Date::getDate( void ) const
  467. {
  468.     static _dosdate_t getDate_temp;
  469.  
  470.     getDate_temp.year  = year;
  471.     getDate_temp.month = month;
  472.     getDate_temp.day   = day;
  473.  
  474.     return getDate_temp;
  475. }
  476.  
  477.  
  478. //─────────────────────────────────────────────────
  479. // Version 4.0 Extension to Public Interface - CDP
  480. //─────────────────────────────────────────────────
  481.  
  482. PUBLIC Date &
  483. Date::Set()
  484. {
  485.     struct _dosdate_t sDate;
  486.     _dos_getdate(&sDate);
  487.  
  488.     month = sDate.month;
  489.     day   = sDate.day;
  490.     year  = sDate.year;
  491.  
  492.     mdy_to_julian();
  493.     return *this;
  494. }
  495.  
  496. PUBLIC Date &
  497. Date::Set(int nMonth, int nDay, int nYear)
  498. {
  499.     month = (unsigned char)nMonth;
  500.     year  = nYear < 0 ? 9999 : nYear;
  501.     year  = nYear > 9999 ? 0 : nYear;
  502.     day   = (unsigned char)(nDay < DaysInMonth() ? nDay : DaysInMonth());
  503.  
  504.     mdy_to_julian();
  505.     return *this;
  506. }
  507.  
  508. PUBLIC Date &
  509. Date::Set(long j)
  510. {
  511.     julian = j;
  512.  
  513.     julian_to_mdy();
  514.     return *this;
  515. }
  516.  
  517.  
  518. PUBLIC int Date::DaysInMonth()
  519. {
  520.     return GauDays[month-1] + (month==2 && isLeapYear());
  521. }
  522.  
  523. PUBLIC int Date::FirstDOM() const
  524. {
  525.     return Date(month, 1, year).NDOW();
  526. }
  527.  
  528. PUBLIC int Date::Day() const
  529. {
  530.     return day;
  531. }
  532.  
  533. PUBLIC int Date::NDOW() const
  534. {
  535.     return day_of_week;
  536. }
  537.  
  538. PUBLIC int Date::NYear4() const
  539. {
  540.     return year;
  541. }
  542.  
  543. PUBLIC int Date::NMonth() const
  544. {
  545.     return month;
  546. }
  547.  
  548. PUBLIC Date & Date::AddWeeks(int nCount)
  549. {
  550.     Set(julian + (long)nCount*7);
  551.     return *this;
  552. }
  553.  
  554.  
  555. PUBLIC Date & Date::AddMonths(int nCount)
  556. {
  557.     month += (unsigned char)nCount;
  558.  
  559.     if (month < 1)
  560.     {
  561.         month = 12;
  562.         year--;
  563.     }
  564.  
  565.     if (month > 12)
  566.     {
  567.         month = 1;
  568.         year++;
  569.     }
  570.  
  571.     mdy_to_julian();
  572.     return *this;
  573. }
  574.  
  575. PUBLIC Date & Date::AddYears(int nCount)
  576. {
  577.     year += nCount;
  578.     mdy_to_julian();
  579.     return *this;
  580. }
  581.  
  582. PUBLIC int Date::WOM()
  583. {
  584.     // Abs day includes the days from previous month that fills up
  585.     // the begin. of the week.
  586.     int nAbsDay = day + FirstDOM()-1;
  587.     return (nAbsDay-NDOW())/7 + 1;
  588. }
  589.  
  590. PUBLIC int Date::WOY()
  591. {
  592. //    ErrFail();
  593.     Date   doTemp(1, 1, year);
  594.     return (int)(((julian - doTemp.julian+1)/7) + 1);
  595. }
  596.  
  597. PUBLIC Date Date::BOM()
  598. {
  599.     return(Date(month, 1, year));
  600. }
  601.  
  602. PUBLIC Date Date::EOM()
  603. {
  604.     return(Date(month+1, 1, year)-1);
  605. }
  606.  
  607. PUBLIC Date Date::BOY()
  608. {
  609.     return(Date(1, 1, year));
  610. }
  611.  
  612. PUBLIC Date Date::EOY()
  613. {
  614.     return(Date(1, 1, year+1)-1);
  615. }
  616.  
  617. PUBLIC char * Date::CMonth()
  618. {
  619.     return(formatDate(MONTH));
  620. }
  621.  
  622. PUBLIC char * Date::CDOW()
  623. {
  624.     return(formatDate(DAY));
  625. }
  626.